using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media.Imaging;
using jSLCore.Client.Presentation.Controls;

namespace jSLCore.Client.Presentation.Common
{
    /// <summary>
    /// WPF
    /// </summary>
    public static class SLWPFSelector
    {
        public static ResourceDictionary LoadVisualResource()
        {
            return new ResourceDictionary { Source = new Uri(@"/jSLCore.Client.Presentation.Wpf;component/DefaultWPFVisualStyle.xaml", UriKind.RelativeOrAbsolute) };
        }

        public static FrameworkElement GetFocusedElement(this FrameworkElement control)
        {
            return FocusManager.GetFocusedElement(control) as FrameworkElement;
        }

        public static string GetDefaultElementPath(this FrameworkElement element)
        {
            if (element is HyperlinkButton) return "Text";
            
            return null;
        }

        public static IEnumerable<FrameworkElement> GetVisualAncestorsAndSelf(this FrameworkElement element)
        {
            var ret = new List<FrameworkElement>(5);

            while (element!=null)
            {
                ret.Add(element);

                var parent = element.Parent as FrameworkElement;
                if (parent == null) parent = element.TemplatedParent as FrameworkElement;
                element = parent;
            }

            return ret.ToArray();
        }

        public static void SetSource(this BitmapImage image,Stream stream)
        {
            image.StreamSource = stream;
        }

        public const string DirtyHack = ".Wpf";
        public static Uri CompileResourceString(string relativeUri)
        {
            return new Uri(string.Format(@"/jSLCore.Client.Presentation{0};component/{1}", DirtyHack, relativeUri),
                           UriKind.RelativeOrAbsolute);
        }

        public static bool ShowUIError(FrameworkElement element,string errorText)
        {
            var binding = new Binding
                              {
                                  RelativeSource = new RelativeSource(RelativeSourceMode.Self)
                              };
            var hackRule = new HackRule(errorText);
            binding.ValidationRules.Add(hackRule);

            var expression = element.SetBinding(DependencyErrorObject.CustomErrorProperty, binding);

            if (!string.IsNullOrEmpty(errorText))
            {
                var template = (ControlTemplate) element.TryFindResource("errorTemplate");

                if(template!=null)
                    Validation.SetErrorTemplate(element,template);
                
                Validation.MarkInvalid(expression, new ValidationError(hackRule, binding));
            }
            else
            {
                Validation.ClearInvalid(expression);
            }

            return true;//we did it
        }
    }
    
    public class DependencyErrorObject : DependencyObject
    {
        public static readonly DependencyProperty CustomErrorProperty = DependencyProperty.Register("CustomError",
                                                                                                    typeof (string),
                                                                                                    typeof (
                                                                                                        DependencyErrorObject
                                                                                                        ));
        public string CustomError
        {
            get { return (string) GetValue(CustomErrorProperty); }
            set
            {
                SetValue(CustomErrorProperty,value);
            }
        }
    }

    public class HackRule : ValidationRule
    {
        private string errorText;

        public HackRule(string errorText)
        {
            this.errorText = errorText;
        }


        public override ValidationResult Validate(object value, CultureInfo cultureInfo)
        {
            return new ValidationResult(false, errorText);
        }
    }
}